package com.xkcyy.one.executor;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xkcyy.one.entity.Tool;
import com.xkcyy.one.exception.BusinessException;
import com.xkcyy.one.service.ToolService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * HTTP工具执行器，用于执行HTTP API类型的工具
 *
 * @author yuand
 */
public class HttpToolExecutor implements ToolExecutor {

    private static final Logger logger = LoggerFactory.getLogger(HttpToolExecutor.class);

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private ToolService toolService;

    @Override
    public boolean supports(Tool tool) {
        return tool != null && Tool.ImplementationType.HTTP.equals(tool.getImplementationType());
    }

    @Override
    public Object execute(Tool tool, Object input) {
        validateInput(tool, input);

        try {
            // 解析工具配置
            Map<String, Object> config = parseToolConfig(tool);
            String url = (String) config.getOrDefault("url", "");
            String method = (String) config.getOrDefault("method", "GET");
            Map<String, String> headers = (Map<String, String>) config.getOrDefault("headers", new HashMap<>());

            // 准备请求
            HttpMethod httpMethod = HttpMethod.valueOf(method.toUpperCase());

            HttpEntity<?> requestEntity = prepareHttpRequest(input, headers);

            // 执行请求
            ResponseEntity<Object> response = restTemplate.exchange(
                    url,
                    httpMethod,
                    requestEntity,
                    Object.class);

            // 处理响应
            return handleResponse(response);

        } catch (Exception e) {
            logger.error("执行HTTP工具调用失败: " + e.getMessage(), e);
            Map<String, Object> errorResult = new HashMap<>();
            errorResult.put("error", true);
            errorResult.put("message", "执行HTTP工具调用失败: " + e.getMessage());
            return errorResult;
        }
    }

    @Override
    public void validateInput(Tool tool, Object input) {
        if (tool == null) {
            throw new IllegalArgumentException("工具定义不能为空");
        }

        Map<String, Object> config = parseToolConfig(tool);
        String url = (String) config.getOrDefault("url", "");

        if (!StringUtils.hasText(url)) {
            throw new IllegalArgumentException("HTTP工具需要配置URL");
        }

        // 输入验证可以根据工具的inputSchema进行更详细的验证
        // 这里简单实现
        if (input == null) {
            throw new IllegalArgumentException("输入参数不能为空");
        }
    }

    /**
     * 解析工具配置
     */
    @SuppressWarnings("unchecked")
    private Map<String, Object> parseToolConfig(Tool tool) {
        try {
            String configuration = tool.getConfiguration();
            if (StringUtils.hasText(configuration)) {
                return objectMapper.readValue(configuration, Map.class);
            } else {
                return new HashMap<>();
            }
        } catch (Exception e) {
            logger.error("解析工具配置失败: " + e.getMessage(), e);
            return new HashMap<>();
        }
    }

    /**
     * 准备HTTP请求
     */
    private HttpEntity<?> prepareHttpRequest(Object input, Map<String, String> configHeaders) {
        HttpHeaders headers = new HttpHeaders();

        // 设置默认内容类型
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));

        // 添加配置中的headers
        if (configHeaders != null) {
            configHeaders.forEach(headers::add);
        }

        return new HttpEntity<>(input, headers);
    }

    /**
     * 处理HTTP响应
     */
    private Object handleResponse(ResponseEntity<Object> response) {
        HttpStatusCode statusCode = response.getStatusCode();
        int statusValue = statusCode.value();
        Object body = response.getBody();

        Map<String, Object> result = new HashMap<>();
        result.put("status", statusValue);
        result.put("success", statusCode.is2xxSuccessful());
        result.put("data", body);

        if (!statusCode.is2xxSuccessful()) {
            result.put("error", true);
            result.put("message", "HTTP调用返回非成功状态码: " + statusValue);
        }

        return result;
    }

    /**
     * 根据路径从响应中提取数据
     */
    private Object extractResponseByPath(String responseBody, String path) throws JsonProcessingException {
        JsonNode rootNode = objectMapper.readTree(responseBody);

        // 如果路径为空，直接返回整个响应
        if (!StringUtils.hasText(path)) {
            return objectMapper.convertValue(rootNode, Object.class);
        }

        // 解析路径并提取数据
        String[] pathParts = path.split("\\.");
        JsonNode currentNode = rootNode;

        for (String part : pathParts) {
            if (currentNode.isArray() && part.matches("\\d+")) {
                // 如果当前节点是数组，且路径部分是数字，则按索引提取
                int index = Integer.parseInt(part);
                if (index >= 0 && index < currentNode.size()) {
                    currentNode = currentNode.get(index);
                } else {
                    throw new BusinessException("响应提取路径无效: 数组索引越界 " + index);
                }
            } else if (currentNode.isObject() && currentNode.has(part)) {
                // 如果当前节点是对象，且有对应字段，则提取字段值
                currentNode = currentNode.get(part);
            } else {
                throw new BusinessException("响应提取路径无效: 找不到字段 " + part);
            }
        }

        // 将提取的节点转换为Java对象
        return objectMapper.convertValue(currentNode, Object.class);
    }

    /**
     * HTTP工具配置类
     */
    private static class HttpToolConfig {
        private String url;
        private String method = "GET";
        private Map<String, String> headers;
        private String bodyField;
        private boolean useFullInputAsBody = true;
        private String responsePath;

        public String getUrl() {
            return url;
        }

        public void setUrl(String url) {
            this.url = url;
        }

        public String getMethod() {
            return method;
        }

        public void setMethod(String method) {
            this.method = method;
        }

        public Map<String, String> getHeaders() {
            return headers;
        }

        public void setHeaders(Map<String, String> headers) {
            this.headers = headers;
        }

        public String getBodyField() {
            return bodyField;
        }

        public void setBodyField(String bodyField) {
            this.bodyField = bodyField;
        }

        public boolean isUseFullInputAsBody() {
            return useFullInputAsBody;
        }

        public void setUseFullInputAsBody(boolean useFullInputAsBody) {
            this.useFullInputAsBody = useFullInputAsBody;
        }

        public String getResponsePath() {
            return responsePath;
        }

        public void setResponsePath(String responsePath) {
            this.responsePath = responsePath;
        }
    }
}